#include "Core.h"
#include "IniFile.h"
#include "GameTime.h"
#include "FilePath.h"
#include "Define.h"
#include "Convert.h"
#include "RenderManager.h"
#include "Resources.h"
#include "DebugLog.h"
#include "Random.h"
#include "InputManager.h"
#include "StateManager.h"
#include "PlayState.h"
#include "PauseState.h"
#include "Controls.h"
#include "Camera.h"

Core::Core(void){}
Core::~Core(void){}

void recreateIniFile(std::shared_ptr<IniFile> file);
bool Core::initialize()
{
	Camera::getSingleton();
	CControls::initialize(2);
	Random::initialize();
	Debug::setLogFile(".\\logs\\log", "txt", true);
	std::shared_ptr<IniFile> iniFile(new IniFile(FILEPATH_CONFIG));
	if (!iniFile->parse())
	{
		recreateIniFile(iniFile);	// recreate and save inifile if not found
	}

	int flags = sf::Style::Close;

	unsigned int screenWidth = stringToNumber<unsigned int>(iniFile->getValue("Video", "Width"));
	unsigned int screenHeight = stringToNumber<unsigned int>(iniFile->getValue("Video", "Height"));
	bool vsync = stringToBool(iniFile->getValue("Video", "Vsync"));
	bool fullscreen = stringToBool(iniFile->getValue("Video", "Fullscreen"));

	if (fullscreen)
	{
		flags |= sf::Style::Fullscreen;
	}

	sf::VideoMode videoMode;
	videoMode.bitsPerPixel = BPP;
	videoMode.width = screenWidth;
	videoMode.height = screenHeight;
	//videoMode = CVideo::testVideoMode(videoMode);

	_window = std::shared_ptr<sf::RenderWindow>(new sf::RenderWindow(videoMode, WINDOW_TITLE, flags));
	_view = std::shared_ptr<sf::View>(new sf::View(sf::FloatRect(0, 0, VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT)));
	_view->setCenter(VSW_05, VSH_05);
	_window->setView(*_view);
	_window->setVerticalSyncEnabled(vsync);
	_inputManager = std::shared_ptr<InputManager>(new InputManager(_window));
	_renderManager = std::unique_ptr<RenderManager>(new RenderManager(_window, _view));
	_renderManager->setRenderState(RS_WINDOW);
	IniFile debug(FILEPATH_DEBUG_INI);
	if (debug.parse())
	{
		Resources::getSingletonPtr()->setMode(stringToNumber<int>(debug.getValue("Filesystem", "LoadFromArchive")), true);
	}
	GameTime::getSingleton();

	_stateManager = std::unique_ptr<StateManager>(new StateManager(_inputManager));
	_stateManager->addState(new PlayState(), true);
	_stateManager->addState(new PauseState(), false);
	_window->setFramerateLimit(60);


	_window->clear(sf::Color::Black);
	_window->display();
	Camera::getSingleton()->initialize(_view, 5.0f);

	return true;
}

void Core::run()
{
	while (_window->isOpen())
	{
		GameTime::getSingleton()->update();
		if (!_inputManager->capture())
			shutdown();
		else
		{
			_renderManager->beginRender();
			_stateManager->update();
			Camera::getSingleton()->update();
			_stateManager->draw(_renderManager.get());
			_renderManager->endRender();
		}
	}
}

void Core::shutdown()
{
	TextureManager::getSingletonPtr()->unloadAllTextures();
	TextureManager::getSingletonPtr()->cleanSingleton();
	AudioManager::getSingletonPtr()->unloadAllSounds();
	AudioManager::getSingletonPtr()->cleanSingleton();
	Resources::getSingletonPtr()->cleanSingleton();
	GameTime::getSingleton()->cleanSingleton();
}

void recreateIniFile(std::shared_ptr<IniFile> file)
{
	/*sf::VideoMode videoMode = CVideo::testVideoMode(videoMode);
	file->addModify("Video", "Width", numberToString(videoMode.width));
	file->addModify("Video", "Height", numberToString(videoMode.height));
	file->addModify("Video", "Fullscreen", "true");
	file->addModify("Video", "Vsync", "false");
	file->addModify("General", "ShowCursor", "false");
	file->addModify("General", "StartState", "IntroState");
	file->save();*/
}